package maven

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"os/exec"
	"strconv"
	"strings"
)

type Mapping struct {
	Id   string
	Name string
}

type BiRelation struct {
	Pid string
	Cid string
}

type DependencyTree struct {
	Id           string           `json:"id", xml:"id"`
	Name         string           `json:"name", xml:"name"`
	Dependencies []DependencyTree `json:"dependencies",xml:"dependencies"`
}

var (
	rootId         string
	idNames        map[string]string
	biRelations    map[string]([]string)
	dependencyTree DependencyTree // 生成的jar包依赖关系
)

// 这个依赖关系是个多叉树

func Print(outputType string) {
	switch outputType {
	case "json":
		jsonOutput, err := json.Marshal(dependencyTree)
		if err != nil {
			fmt.Println(err.Error())
			return
		}
		fmt.Println(string(jsonOutput))
	case "xml":
		return
	}
}

// exported func
func MvnCheck(projectpath string) {
	mvnCommand(projectpath)
	buildDependencyTree()
}

func buildDependencyTree() {
	dependencyTree.Id = rootId
	dependencyTree.Name = idNames[rootId]
	build(&dependencyTree, idNames, biRelations)
}

func build(treePtr *DependencyTree, idnames map[string]string, biRelations map[string]([]string)) {
	for _, id := range biRelations[treePtr.Id] {
		treePtr.Dependencies = append(treePtr.Dependencies, DependencyTree{
			Id:   id,
			Name: idnames[id],
		})
	}
	delete(biRelations, treePtr.Id)
	for k, _ := range treePtr.Dependencies {
		build(&treePtr.Dependencies[k], idnames, biRelations)
	}
}

func mvnCommand(projectPath string) error {

	var flag int = 0

	idNames = make(map[string]string)
	biRelations = make(map[string]([]string))

	reader, writer := io.Pipe()
	defer reader.Close()
	defer writer.Close()

	// mvn dependency:tree -DoutputType=tgf --batch-mode -Dscope=compile
	var name string = "mvn"
	var args []string = []string{
		"dependency:tree",
		"-DoutputType=tgf",
		"--batch-mode",
		"-Dscope=compile",
	}
	cmd := exec.Command(name, args...)
	cmd.Dir = projectPath
	stdout, _ := cmd.StdoutPipe()
	scanner := bufio.NewReader(stdout)

	if err := cmd.Start(); err != nil {
		return err
	}

	for {
		line, _, err := scanner.ReadLine()
		if err != nil {
			break
		}
		// TODO:把这儿东西转化成结构化的，然后根据父子关系构造依赖
		arr := strings.Split(string(line), " ")
		arr = arr[1:]

		// 这也太丑了
		// 这儿是id到jar包的映射
		if len(arr) == 2 {
			_, err := strconv.Atoi(arr[0])
			if err == nil {
				if flag == 0 {
					rootId = arr[0]
					flag = 1
				}
				// fmt.Println(string(line))
				idNames[arr[0]] = arr[1]
			}
		}
		// 这儿是不同包id之间的关系
		if len(arr) == 3 {
			_, err1 := strconv.Atoi(arr[0])
			_, err2 := strconv.Atoi(arr[1])
			if err1 == nil && err2 == nil {
				// fmt.Println(string(line))
				biRelations[arr[0]] = append(biRelations[arr[0]], arr[1])
			}
		}
	}
	return nil
}
